#include <stdio.h>
#include <allegro.h>

#include "structs.h"
#include "common.h"
#include "m68k.h"
#include "objects.h"
#include "script.h"
#include "obj01.h"

void LoadBinary(unsigned char o, const char *filename){
	FILE *file_68000;
	int count;
	
	#ifdef ALLEGRO_DOS
	allegro_message("Loading 68000 binary file \"%s\"...\n", filename);
	#endif
	
	file_68000 = fopen(filename, "rb");
	if(file_68000 == NULL){
		allegro_message("Could not open file \"%s\"...\n", filename);
		return;
	}
	obj_script_type[o] = SCRIPT_TYPE_MOTOROLA;
	obj_script_start[o] = script_size;
	obj_script_size[o] = script_size;
	fseek(file_68000, 0, SEEK_END);
	count = ftell(file_68000);
	script_size += count;
	obj_script_size[o] = script_size - obj_script_size[o];
	fseek(file_68000, 0, SEEK_SET);
	script = (char*)realloc(script, script_size);
	fread(&script[obj_script_start[o]], 1, count, file_68000);
	fclose(file_68000);
}

void RunScript(unsigned short NodeNumber){
	FILE *ramdump;
	int n;
	int i;
	/* The following instructions are implemented
		- FULLY IMPLEMENTED AND TESTED
		@ PARTIALLY IMPLEMENTED
		? UNTESTED
	
	- ADD		- ADDA		- ADDI		- ADDQ
	- AND		- ANDI		- ANDI CCR	- ANDI SR
	@ ASL		@ ASR
	- Bcc		- BRA		- BSR
	- BCHG		- BCLR		- BSET		- BTST
	- CLR
	- CMP		- CMPA		- CMPI
	- DBcc
	- EOR		- EORI		- EORI CCR	- EORI SR
	- EXT
	- JMP		- JSR
	- LEA
	@ LSL		@ LSR
	- MOVE		- MOVEA		- MOVEM		- MOVEQ
	- MULS		- MULU
	- NEG		- NEGX
	- NOP
	- NOT
	- OR		- ORI		- ORI CCR	- ORI SR
	- RTS
	- SUB		- SUBA		- SUBI		- SUBQ
	- SWAP
	- TST
	*/
	
	DataIn();
	
	#ifdef ENABLE_LOGGING
	WriteLog("*******************************");
	WriteLog("START OF LOG");
	#endif
	for(pc=0; pc < obj_script_size[objObject[NodeNumber].type]; 0){
		#ifdef ENABLE_LOGGING
		WriteLog("*******************************");
		VarLog(REG_PC);
		#endif
		i = (obj_script[pc] << 8) + obj_script[pc+1];
		#ifdef ENABLE_LOGGING
		var_temp = i;
		VarLog(VAR_VAR_TEMP);
		WriteLog("\n");
		#endif
		
		pc += 2;
		switch(i >> 12){
			case 0:
				switch(i & 0xF00){
					case 0:
						op_ori(i);
						break;
					case 0x200:
						op_andi(i);
						break;
					case 0x400:
						op_subi(i);
						break;
					case 0x600:
						op_addi(i);
						break;
					case 0x800:
						switch(i & 0xC0){
							case 0:
								op_btst(i);
								break;
							case 0x40:
								op_bchg(i);
								break;
							case 0x80:
								op_bclr(i);
								break;
							case 0xC0:
								op_bset(i);
								break;
						}
						break;
					case 0xA00:
						op_eori(i);
						break;
					case 0xC00:
						op_cmpi(i);
						break;
					default:
						if((i & 0x1C0) == 0x100){
							op_btst(i);
							break;
						}
						else if((i & 0x1C0) == 0x140){
							op_bchg(i);
							break;
						}
						else if((i & 0x1C0) == 0x180){
							op_bclr(i);
							break;
						}
						else if((i & 0x1C0) == 0x1C0){
							op_bset(i);
							break;
						}
						op_add(i);
				}
				break;
			case 1:
				op_move(i);
				break;
			case 2:
				op_move(i);
				break;
			case 3:
				op_move(i);
				break;
			case 4:
				if((i & 0xFB8) == 0x880){
					op_ext(i);
					break;
				}
				if((i & 0xB80) == 0x880){
					op_movem(i);
					break;
				}
				if((i & 0x1C0) == 0x1C0){
					op_lea(i);
					break;
				}
				switch(i & 0xF00){
					case 0:
						op_negx(i);
						break;
					case 0x200:
						op_clr(i);
						break;
					case 0x400:
						op_neg(i);
						break;
					case 0x600:
						op_not(i);
						break;
					case 0x800:
						if((i & 0xF8) == 0x40){
							op_swap(i);
							break;
						}
						break;
					case 0xA00:
						op_tst(i);
						break;
					case 0xE00:
						if(i & 0x80){
							op_jmp(i);
							break;
						}
						else if(i == 0x4E71){
							#ifdef ENABLE_LOGGING
							WriteLog("NOP");
							#endif
							break;
						}
						else if(i == 0x4E75){
							#ifdef ENABLE_LOGGING
							WriteLog("RTS");
							#endif
							if(reg_a[7] == 0xFFFFFFFC)
								pc = script_size;
							else{
								//allegro_message("RTS\n\npc = %X", pc);
								//allegro_message("ram_68k[0xFFF8] = %X", (int)ram_68k[0xFFF8]);
								pc = *(int *)(&ram_68k[reg_a[7] & 0xFFFF]);
								reg_a[7] += 4;
								//allegro_message("RTS\n\npc = %X", pc);
							}
							break;
						}
				}
				break;
			case 5:
				if((i & 0xF8) == 0xC8){
					op_dbcc(i);
					break;
				}
				if(i & 0x100){
					op_subq(i);
					break;
				}
				op_addq(i);
				break;
			case 6:
				op_bcc(i);
				break;
			case 7:
				op_moveq(i);
				break;
			case 8:
				op_or(i);
				break;
			case 9:
				op_sub(i);
				break;
			case 0xB:
				if(i & 0x100){
					op_eor(i);
					break;
				}
				op_cmp(i);
				break;
			case 0xC:
				if(((i >> 6) & 3) == 3){
					op_muls(i);
					break;
				}
				op_and(i);
				break;
			case 0xD:
				op_add(i);
				break;
			case 0xE:
				op_lsd(i);
				break;
			case 0xF:
				DataOut();
				switch(i & 0xF00){
					case 0x0:
						pro_jump(i, NodeNumber);
						break;
					case 0x100:
						pro_call(i, NodeNumber);
						break;
				}
				DataIn();
				break;
			default:
				#ifdef ENABLE_LOGGING
				WriteLog("INVALID OPCODE!");
				#endif
				//DumpLog("Motorola.log");
				allegro_message("INVALID OPCODE!\n\n i = 0x%04X\npc = 0x%04X", i, pc);
				break;
		}
		
		#ifdef ENABLE_LOGGING
		d0 = reg_d[0];
		d1 = reg_d[1];
		d2 = reg_d[2];
		d3 = reg_d[3];
		d4 = reg_d[4];
		d5 = reg_d[5];
		d6 = reg_d[6];
		d7 = reg_d[7];
		a0 = reg_a[0];
		a1 = reg_a[1];
		a2 = reg_a[2];
		a3 = reg_a[3];
		a4 = reg_a[4];
		a5 = reg_a[5];
		a6 = reg_a[6];
		a7 = reg_a[7];
		VarLog(REG_SR);
		VarLog(REG_D0);
		VarLog(REG_D1);
		VarLog(REG_D2);
		VarLog(REG_D3);
		VarLog(REG_D4);
		VarLog(REG_D5);
		VarLog(REG_D6);
		VarLog(REG_D7);
		VarLog(REG_A0);
		VarLog(REG_A1);
		VarLog(REG_A2);
		VarLog(REG_A3);
		VarLog(REG_A4);
		VarLog(REG_A5);
		VarLog(REG_A6);
		VarLog(REG_A7);
		
		WriteLog("\t~~~ SONIC VALUES ~~~~~~~~~~~~~");
		var_temp = (ram_68k[0xFFFF - 0xB002] << 8) + ram_68k[0xFFFF - 0xB003];
		WriteLog("\t_art_tile");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB014] << 8) + ram_68k[0xFFFF - 0xB015];
		WriteLog("\t_inertia");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB02E] << 8) + ram_68k[0xFFFF - 0xB02F];
		WriteLog("\t_move_lock");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB018];
		WriteLog("\t_priority");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB001];
		WriteLog("\t_render_flags");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB024];
		WriteLog("\t_routine");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB022];
		WriteLog("\t_status");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB028];
		WriteLog("\t_subtype");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB008] << 8) + ram_68k[0xFFFF - 0xB009];
		WriteLog("\t_x_pos");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB010] << 8) + ram_68k[0xFFFF - 0xB011];
		WriteLog("\t_x_vel");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB00C] << 8) + ram_68k[0xFFFF - 0xB00D];
		WriteLog("\t_y_pos");
		VarLog(VAR_VAR_TEMP);
		WriteLog("RAM:");
		RamLog(0xB000);
		
		WriteLog("\t~~~ OBJECT VALUES ~~~~~~~~~~~~");
		var_temp = (ram_68k[0xFFFF - 0xB102] << 8) + ram_68k[0xFFFF - 0xB103];
		WriteLog("\t_art_tile");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB114] << 8) + ram_68k[0xFFFF - 0xB115];
		WriteLog("\t_inertia");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB12E] << 8) + ram_68k[0xFFFF - 0xB12F];
		WriteLog("\t_move_lock");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB118];
		WriteLog("\t_priority");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB101];
		WriteLog("\t_render_flags");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB124];
		WriteLog("\t_routine");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB122];
		WriteLog("\t_status");
		VarLog(VAR_VAR_TEMP);
		var_temp = ram_68k[0xFFFF - 0xB128];
		WriteLog("\t_subtype");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB108] << 8) + ram_68k[0xFFFF - 0xB109];
		WriteLog("\t_x_pos");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB110] << 8) + ram_68k[0xFFFF - 0xB111];
		WriteLog("\t_x_vel");
		VarLog(VAR_VAR_TEMP);
		var_temp = (ram_68k[0xFFFF - 0xB10C] << 8) + ram_68k[0xFFFF - 0xB10D];
		WriteLog("\t_y_pos");
		VarLog(VAR_VAR_TEMP);
		WriteLog("RAM:");
		RamLog(0xB100);
		#endif
		
		//DumpLog("Motorola.log");
		//if(i == 0x4441)
		//	allegro_message("HOLY");
		//fseek(ramdump, 0, SEEK_SET);
		//for(n=0; n < 0x10000; n++)
		//	fwrite(&ram_68k[n], 1, 1, ramdump);
		//allegro_message("%X\n%X", p->x_pos, *(short *)(&ram_68k[0xB008]));
	}
	
	#ifdef ENABLE_LOGGING
	WriteLog("END OF LOG");
	DumpLog("Motorola.log");
	#endif
	//if(obj_script[0x13] != 0xC){
	//	allegro_message("CRAP");
	//	rest(40);
	//}
	
	/*ramdump = fopen("ramdump", "w+b");
	for(i=0xFFFF; i >=0; i--)
		fwrite(&ram_68k[i], 1, 1, ramdump);
	fclose(ramdump);*/
	
	DataOut();
	
	//fclose(ramdump);
	//allegro_message("PASS");
}



void pro_jump(short data, unsigned short NodeNumber){	// F0xx
	OBJECT *o = &objObject[NodeNumber];
	
	switch(data & 0xFF){
		case 0x0:
			CalcSine();
			break;
		case 0x20:
			//DestroyObject(o, NodeNumber);
			PollObjectFrame(NodeNumber);
			break;
		case 0x60:
			PlayFM(d0 & 0x7F, 2, 0);
			break;
		case 0x61:
			PlayPCM(d0 & 0x7F, 2, 0);
			break;
		case 0x62:
			PlayFM(d0 & 0x7F, 0, 0);
			break;
		case 0x63:
			PlayPCM(d0 & 0x7F, 0, 0);
			break;
		case 0x81:
			Sonic_ResetOnFloor(1);
			break;
		case 0x83:
			FindFloor();
			break;
	}
	
	#ifdef ENABLE_LOGGING
	WriteLog("RTS");
	#endif
	if(reg_a[7] == 0xFFFFFFFC)
		pc = script_size;
	else{
		//allegro_message("RTS\n\npc = %X", pc);
		//allegro_message("ram_68k[0xFFF8] = %X", (int)ram_68k[0xFFF8]);
		pc = *(int *)(&ram_68k[reg_a[7] & 0xFFFF]);
		reg_a[7] += 4;
		a7 = reg_a[7];
		//allegro_message("RTS\n\npc = %X", pc);
	}
}

void pro_call(short data, unsigned short NodeNumber){	// F1xx
	reg_a[7] -= 4;
	a7 = reg_a[7];
	*(int *)(&ram_68k[reg_a[7] & 0xFFFF]) = pc;
	
	pro_jump(data, NodeNumber);
}







/*void pro_call(int target){
	if(target >= 0x19C8A && target < 0x19F50)
		SlopeObject(target);
}







void SlopeObject(int target){
	reg_a[1] = 0xB000;
	reg_d[6] = 3;
	
	reg_a[7] -= 4;
	ea = &ram_68k[reg_a[7]];
	*(int *)ea = reg_d[1];
	reg_a[7] -= 4;
	ea = &ram_68k[reg_a[7]];
	*(int *)ea = reg_d[2];
	reg_a[7] -= 4;
	ea = &ram_68k[reg_a[7]];
	*(int *)ea = reg_d[3];
	reg_a[7] -= 4;
	ea = &ram_68k[reg_a[7]];
	*(int *)ea = reg_d[4];
	
	pro_call(0x19CA0);
	
	ea = &ram_68k[reg_a[7]];
	reg_d[4] = *(int *)ea;
	reg_a[7] += 4;
	ea = &ram_68k[reg_a[7]];
	reg_d[3] = *(int *)ea;
	reg_a[7] += 4;
	ea = &ram_68k[reg_a[7]];
	reg_d[2] = *(int *)ea;
	reg_a[7] += 4;
	ea = &ram_68k[reg_a[7]];
	reg_d[1] = *(int *)ea;
	reg_a[7] += 4;
	
	reg_a[1] = 0xB040;
	(*(char *)(&reg_d[6])) += 1;
	
SlopeObject_SingleCharacter:
	ea = &ram_68k[0xFFFF - (reg_a[0] + 0x22)];
	if(((*(char *)ea) >> reg_d[6]) & 1){
		pro_call(0x19CA0);
		return;
	}
	(*(short *)(&reg_d[2])) = (*(short *)(&reg_d[1]));
	(*(short *)(&reg_d[2])) += (*(short *)(&reg_d[2]));
	//btst #1,status(a1)	// solid.asm : line 661
}*/



void DataIn(){
	ram_68k[0xFFFF - 0xB001 - ((frame-1) << 6)] = p->render_flags;
	ram_68k[0xFFFF - 0xB002 - ((frame-1) << 6)] = p->art_tile >> 8;
	ram_68k[0xFFFF - 0xB003 - ((frame-1) << 6)] = p->art_tile;
	ram_68k[0xFFFF - 0xB004 - ((frame-1) << 6)] = p->mappings >> 24;
	ram_68k[0xFFFF - 0xB005 - ((frame-1) << 6)] = p->mappings >> 16;
	ram_68k[0xFFFF - 0xB006 - ((frame-1) << 6)] = p->mappings >> 8;
	ram_68k[0xFFFF - 0xB007 - ((frame-1) << 6)] = p->mappings;
	ram_68k[0xFFFF - 0xB008 - ((frame-1) << 6)] = p->x_pos >> 8;
	ram_68k[0xFFFF - 0xB009 - ((frame-1) << 6)] = p->x_pos;
	ram_68k[0xFFFF - 0xB00A - ((frame-1) << 6)] = p->x_pos_pre >> 8;
	ram_68k[0xFFFF - 0xB00B - ((frame-1) << 6)] = p->x_pos_pre;
	ram_68k[0xFFFF - 0xB00C - ((frame-1) << 6)] = p->y_pos >> 8;
	ram_68k[0xFFFF - 0xB00D - ((frame-1) << 6)] = p->y_pos;
	ram_68k[0xFFFF - 0xB00E - ((frame-1) << 6)] = p->y_pos_pre >> 8;
	ram_68k[0xFFFF - 0xB00F - ((frame-1) << 6)] = p->y_pos_pre;
	ram_68k[0xFFFF - 0xB010 - ((frame-1) << 6)] = p->x_vel >> 8;
	ram_68k[0xFFFF - 0xB011 - ((frame-1) << 6)] = p->x_vel;
	ram_68k[0xFFFF - 0xB012 - ((frame-1) << 6)] = p->y_vel >> 8;
	ram_68k[0xFFFF - 0xB013 - ((frame-1) << 6)] = p->y_vel;
	ram_68k[0xFFFF - 0xB014 - ((frame-1) << 6)] = p->inertia >> 8;
	ram_68k[0xFFFF - 0xB015 - ((frame-1) << 6)] = p->inertia;
	ram_68k[0xFFFF - 0xB016 - ((frame-1) << 6)] = p->y_radius;
	ram_68k[0xFFFF - 0xB017 - ((frame-1) << 6)] = p->x_radius;
	ram_68k[0xFFFF - 0xB018 - ((frame-1) << 6)] = p->priority;
	ram_68k[0xFFFF - 0xB019 - ((frame-1) << 6)] = p->width_pixels;
	ram_68k[0xFFFF - 0xB01A - ((frame-1) << 6)] = p->mapping_frame;
	ram_68k[0xFFFF - 0xB01B - ((frame-1) << 6)] = p->anim_frame;
	ram_68k[0xFFFF - 0xB01C - ((frame-1) << 6)] = p->anim;
	ram_68k[0xFFFF - 0xB01D - ((frame-1) << 6)] = p->next_anim;
	ram_68k[0xFFFF - 0xB01E - ((frame-1) << 6)] = p->anim_frame_duration;/////////////
	ram_68k[0xFFFF - 0xB022 - ((frame-1) << 6)] = p->status;
	ram_68k[0xFFFF - 0xB024 - ((frame-1) << 6)] = p->routine;
	ram_68k[0xFFFF - 0xB025 - ((frame-1) << 6)] = p->routine_secondary;
	ram_68k[0xFFFF - 0xB026 - ((frame-1) << 6)] = p->angle;
	ram_68k[0xFFFF - 0xB027 - ((frame-1) << 6)] = p->flip_angle;
	ram_68k[0xFFFF - 0xB028 - ((frame-1) << 6)] = p->air_left;
	ram_68k[0xFFFF - 0xB029 - ((frame-1) << 6)] = p->flip_turned;
	ram_68k[0xFFFF - 0xB02A - ((frame-1) << 6)] = p->obj_control;
	ram_68k[0xFFFF - 0xB02B - ((frame-1) << 6)] = p->status_secondary;
	ram_68k[0xFFFF - 0xB02C - ((frame-1) << 6)] = p->flips_remaining;
	ram_68k[0xFFFF - 0xB02D - ((frame-1) << 6)] = p->flip_speed;
	ram_68k[0xFFFF - 0xB02E - ((frame-1) << 6)] = p->move_lock >> 8;
	ram_68k[0xFFFF - 0xB02F - ((frame-1) << 6)] = p->move_lock;
	ram_68k[0xFFFF - 0xB030 - ((frame-1) << 6)] = p->invulnerable_time >> 8;
	ram_68k[0xFFFF - 0xB031 - ((frame-1) << 6)] = p->invulnerable_time;
	ram_68k[0xFFFF - 0xB032 - ((frame-1) << 6)] = p->invincibility_time >> 8;
	ram_68k[0xFFFF - 0xB033 - ((frame-1) << 6)] = p->invincibility_time;
	ram_68k[0xFFFF - 0xB034 - ((frame-1) << 6)] = p->speedshoes_time >> 8;
	ram_68k[0xFFFF - 0xB035 - ((frame-1) << 6)] = p->speedshoes_time;
	ram_68k[0xFFFF - 0xB036 - ((frame-1) << 6)] = p->next_tilt;
	ram_68k[0xFFFF - 0xB037 - ((frame-1) << 6)] = p->tilt;
	ram_68k[0xFFFF - 0xB038 - ((frame-1) << 6)] = p->stick_to_convex;
	ram_68k[0xFFFF - 0xB039 - ((frame-1) << 6)] = p->spindash_flag;
	ram_68k[0xFFFF - 0xB03A - ((frame-1) << 6)] = p->spindash_counter >> 8;
	ram_68k[0xFFFF - 0xB03B - ((frame-1) << 6)] = p->spindash_counter;
	ram_68k[0xFFFF - 0xB03C - ((frame-1) << 6)] = p->jumping;
	ram_68k[0xFFFF - 0xB03D - ((frame-1) << 6)] = p->interact;
	ram_68k[0xFFFF - 0xB03E - ((frame-1) << 6)] = p->layer - 4; // subtract 4
	ram_68k[0xFFFF - 0xB03F - ((frame-1) << 6)] = p->layer_plus - 4; // subtract 4
	
	ram_68k[0xFFFF - 0xEE00 - ((frame-1) << 5)] = p->Camera_X_pos >> 8;
	ram_68k[0xFFFF - 0xEE01 - ((frame-1) << 5)] = p->Camera_X_pos;
	ram_68k[0xFFFF - 0xEE04 - ((frame-1) << 5)] = p->Camera_Y_pos >> 8;
	ram_68k[0xFFFF - 0xEE05 - ((frame-1) << 5)] = p->Camera_Y_pos;
	ram_68k[0xFFFF - 0xEEC6] = p->Camera_Max_Y_pos >> 8;
	ram_68k[0xFFFF - 0xEEC7] = p->Camera_Max_Y_pos;
	ram_68k[0xFFFF - 0xEEC8] = p->Camera_Min_X_pos >> 8;
	ram_68k[0xFFFF - 0xEEC9] = p->Camera_Min_X_pos;
	ram_68k[0xFFFF - 0xEECA] = p->Camera_Max_X_pos >> 8;
	ram_68k[0xFFFF - 0xEECB] = p->Camera_Max_X_pos;
	ram_68k[0xFFFF - 0xEECC] = p->Camera_Min_Y_pos >> 8;
	ram_68k[0xFFFF - 0xEECD] = p->Camera_Min_Y_pos;
	ram_68k[0xFFFF - 0xEECE] = p->Camera_Max_Y_pos_now >> 8;
	ram_68k[0xFFFF - 0xEECF] = p->Camera_Max_Y_pos_now;
	ram_68k[0xFFFF - 0xF7D0] = Chain_Bonus_counter >> 8;
	ram_68k[0xFFFF - 0xF7D1] = Chain_Bonus_counter;
	ram_68k[0xFFFF - 0xF7D6] = Update_Bonus_score;
	ram_68k[0xFFFF - 0xF7DA] = p->Camera_X_pos_coarse;
	
	ram_68k[0xFFFF - 0xFE10] = zone;
	ram_68k[0xFFFF - 0xFE11] = act;
	ram_68k[0xFFFF - 0xFE12] = p->Life_count;
	ram_68k[0xFFFF - 0xFE1A] = Time_Over_flag;
	ram_68k[0xFFFF - 0xFE1B] = p->Extra_life_flags;
	ram_68k[0xFFFF - 0xFE1C] = Update_HUD_lives;
	ram_68k[0xFFFF - 0xFE1D] = Update_HUD_rings;
	ram_68k[0xFFFF - 0xFE1E] = Update_HUD_timer;
	ram_68k[0xFFFF - 0xFE1F] = Update_HUD_score;
	ram_68k[0xFFFF - 0xFE20] = p->Ring_count >> 8;
	ram_68k[0xFFFF - 0xFE21] = p->Ring_count;
	ram_68k[0xFFFF - 0xFE22] = 0;
	ram_68k[0xFFFF - 0xFE23] = Timer_minute;
	ram_68k[0xFFFF - 0xFE24] = Timer_second;
	ram_68k[0xFFFF - 0xFE25] = Timer_millisecond;
	
	ram_68k[0xFFFF - 0xFE30] = Last_star_pole_hit;
	
	ram_68k[0xFFFF - 0xFE74] = counter_fe74 >> 8;
	ram_68k[0xFFFF - 0xFE75] = counter_fe74;
	
	ram_68k[0xFFFF - 0xFEC8] = Update_HUD_lives_2P;
	ram_68k[0xFFFF - 0xFEC9] = Update_HUD_rings_2P;
	ram_68k[0xFFFF - 0xFECA] = Update_HUD_timer_2P;
	ram_68k[0xFFFF - 0xFECB] = Update_HUD_score_2P;
	ram_68k[0xFFFF - 0xFECC] = Time_Over_flag_2P;
	
	ram_68k[0xFFFF - 0xFEE0] = Last_star_pole_hit_2P;
	
	ram_68k[0xFFFF - 0xFF40] = Perfect_rings_left >> 8;
	ram_68k[0xFFFF - 0xFF41] = Perfect_rings_left;
	
	ram_68k[0xFFFF - 0xFFD8] = Two_player_mode;
	
	/*reg_a[0] = a0;
	reg_a[1] = a1;
	reg_a[2] = a2;
	reg_a[3] = a3;
	reg_a[4] = a4;
	reg_a[5] = a5;
	reg_a[6] = a6;
	reg_a[7] = a7;*/
	reg_d[0] = d0;
	reg_d[1] = d1;
	reg_d[2] = d2;
	reg_d[3] = d3;
	reg_d[4] = d4;
	reg_d[5] = d5;
	reg_d[6] = d6;
	reg_d[7] = d7;
}

void DataOut(){
	p->render_flags = ram_68k[0xFFFF - 0xB001 - ((frame-1) << 6)];
	p->art_tile = (ram_68k[0xFFFF - 0xB002 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB003 - ((frame-1) << 6)];
	p->mappings = (ram_68k[0xFFFF - 0xB004 - ((frame-1) << 6)] << 24) + (ram_68k[0xFFFF - 0xB005 - ((frame-1) << 6)] << 16);
				+ (ram_68k[0xFFFF - 0xB006 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB007 - ((frame-1) << 6)];
	p->x_pos = (ram_68k[0xFFFF - 0xB008 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB009 - ((frame-1) << 6)];
	p->x_pos_pre = (ram_68k[0xFFFF - 0xB00A - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB00B - ((frame-1) << 6)];
	p->y_pos = (ram_68k[0xFFFF - 0xB00C - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB00D - ((frame-1) << 6)];
	p->y_pos_pre = (ram_68k[0xFFFF - 0xB00E - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB00F - ((frame-1) << 6)];
	p->x_vel = (ram_68k[0xFFFF - 0xB010 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB011 - ((frame-1) << 6)];
	p->y_vel = (ram_68k[0xFFFF - 0xB012 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB013 - ((frame-1) << 6)];
	p->inertia = (ram_68k[0xFFFF - 0xB014 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB015 - ((frame-1) << 6)];
	p->y_radius = ram_68k[0xFFFF - 0xB016 - ((frame-1) << 6)];
	p->x_radius = ram_68k[0xFFFF - 0xB017 - ((frame-1) << 6)];
	p->priority = ram_68k[0xFFFF - 0xB018 - ((frame-1) << 6)];
	p->width_pixels = ram_68k[0xFFFF - 0xB019 - ((frame-1) << 6)];
	p->mapping_frame = ram_68k[0xFFFF - 0xB01A - ((frame-1) << 6)];
	p->anim_frame = ram_68k[0xFFFF - 0xB01B - ((frame-1) << 6)];
	p->anim = ram_68k[0xFFFF - 0xB01C - ((frame-1) << 6)];
	p->next_anim = ram_68k[0xFFFF - 0xB01D - ((frame-1) << 6)];
	p->anim_frame_duration = ram_68k[0xFFFF - 0xB01E - ((frame-1) << 6)];////////////
	p->status = ram_68k[0xFFFF - 0xB022 - ((frame-1) << 6)];
	p->routine = ram_68k[0xFFFF - 0xB024 - ((frame-1) << 6)];
	p->routine_secondary = ram_68k[0xFFFF - 0xB025 - ((frame-1) << 6)];
	p->angle = ram_68k[0xFFFF - 0xB026 - ((frame-1) << 6)];
	p->flip_angle = ram_68k[0xFFFF - 0xB027 - ((frame-1) << 6)];
	p->air_left = ram_68k[0xFFFF - 0xB028 - ((frame-1) << 6)];
	p->flip_turned = ram_68k[0xFFFF - 0xB029 - ((frame-1) << 6)];
	p->obj_control = ram_68k[0xFFFF - 0xB02A - ((frame-1) << 6)];
	p->status_secondary = ram_68k[0xFFFF - 0xB02B - ((frame-1) << 6)];
	p->flips_remaining = ram_68k[0xFFFF - 0xB02C - ((frame-1) << 6)];
	p->flip_speed = ram_68k[0xFFFF - 0xB02D - ((frame-1) << 6)];
	p->move_lock = (ram_68k[0xFFFF - 0xB02E - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB02F - ((frame-1) << 6)];
	p->invulnerable_time = (ram_68k[0xFFFF - 0xB030 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB031 - ((frame-1) << 6)];
	p->invincibility_time = (ram_68k[0xFFFF - 0xB032 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB033 - ((frame-1) << 6)];
	p->speedshoes_time = (ram_68k[0xFFFF - 0xB034 - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB035 - ((frame-1) << 6)];
	p->next_tilt = ram_68k[0xFFFF - 0xB036 - ((frame-1) << 6)];
	p->tilt = ram_68k[0xFFFF - 0xB037 - ((frame-1) << 6)];
	p->stick_to_convex = ram_68k[0xFFFF - 0xB038 - ((frame-1) << 6)];
	p->spindash_flag = ram_68k[0xFFFF - 0xB039 - ((frame-1) << 6)];
	p->spindash_counter = (ram_68k[0xFFFF - 0xB03A - ((frame-1) << 6)] << 8) + ram_68k[0xFFFF - 0xB03B - ((frame-1) << 6)];
	p->jumping = ram_68k[0xFFFF - 0xB03C - ((frame-1) << 6)];
	p->interact = ram_68k[0xFFFF - 0xB03D - ((frame-1) << 6)];
	p->layer = ram_68k[0xFFFF - 0xB03E - ((frame-1) << 6)] + 4; // add four
	p->layer_plus = ram_68k[0xFFFF - 0xB03F - ((frame-1) << 6)] + 4; // add four
	
	p->Camera_X_pos = (ram_68k[0xFFFF - 0xEE00 - ((frame-1) << 5)] << 8) + ram_68k[0xFFFF - 0xEE01 - ((frame-1) << 5)];
	p->Camera_Y_pos = (ram_68k[0xFFFF - 0xEE04 - ((frame-1) << 5)] << 8) + ram_68k[0xFFFF - 0xEE05 - ((frame-1) << 5)];
	p->Camera_Max_Y_pos = (ram_68k[0xFFFF - 0xEEC6] << 8) + ram_68k[0xFFFF - 0xEEC7];
	p->Camera_Min_X_pos = (ram_68k[0xFFFF - 0xEEC8] << 8) + ram_68k[0xFFFF - 0xEEC9];
	p->Camera_Max_X_pos = (ram_68k[0xFFFF - 0xEECA] << 8) + ram_68k[0xFFFF - 0xEECB];
	p->Camera_Min_Y_pos = (ram_68k[0xFFFF - 0xEECC] << 8) + ram_68k[0xFFFF - 0xEECD];
	p->Camera_Max_Y_pos_now = (ram_68k[0xFFFF - 0xEECE] << 8) + ram_68k[0xFFFF - 0xEECF];
	Chain_Bonus_counter = (ram_68k[0xFFFF - 0xF7D0] << 8) + ram_68k[0xFFFF - 0xF7D1];
	Update_Bonus_score = ram_68k[0xFFFF - 0xF7D6];
	p->Camera_X_pos_coarse = ram_68k[0xFFFF - 0xF7DA];
	
	zone = ram_68k[0xFFFF - 0xFE10];
	act = ram_68k[0xFFFF - 0xFE11];
	p->Life_count = ram_68k[0xFFFF - 0xFE12];
	
	Time_Over_flag = ram_68k[0xFFFF - 0xFE1A];
	p->Extra_life_flags = ram_68k[0xFFFF - 0xFE1B];
	Update_HUD_lives = ram_68k[0xFFFF - 0xFE1C];
	Update_HUD_rings = ram_68k[0xFFFF - 0xFE1D];
	Update_HUD_timer = ram_68k[0xFFFF - 0xFE1E];
	Update_HUD_score = ram_68k[0xFFFF - 0xFE1F];
	p->Ring_count = (ram_68k[0xFFFF - 0xFE20] << 8) + ram_68k[0xFFFF - 0xFE21];
	Timer_minute = ram_68k[0xFFFF - 0xFE23];
	Timer_second = ram_68k[0xFFFF - 0xFE24];
	Timer_millisecond = ram_68k[0xFFFF - 0xFE25];
	
	Last_star_pole_hit = ram_68k[0xFFFF - 0xFE30];
	
	counter_fe74 = (ram_68k[0xFFFF - 0xFE74] << 8) + ram_68k[0xFFFF - 0xFE75];
	
	Update_HUD_lives_2P = ram_68k[0xFFFF - 0xFEC8];
	Update_HUD_rings_2P = ram_68k[0xFFFF - 0xFEC9];
	Update_HUD_timer_2P = ram_68k[0xFFFF - 0xFECA];
	Update_HUD_score_2P = ram_68k[0xFFFF - 0xFECB];
	Time_Over_flag_2P = ram_68k[0xFFFF - 0xFECC];
	
	Last_star_pole_hit_2P = ram_68k[0xFFFF - 0xFEE0];
	
	Perfect_rings_left = (ram_68k[0xFFFF - 0xFF40] << 8) + ram_68k[0xFFFF - 0xFF41];
	
	Two_player_mode = ram_68k[0xFFFF - 0xFFD8];
	
	/*a0 = reg_a[0];
	a1 = reg_a[1];
	a2 = reg_a[2];
	a3 = reg_a[3];
	a4 = reg_a[4];
	a5 = reg_a[5];
	a6 = reg_a[6];
	a7 = reg_a[7];*/
	d0 = reg_d[0];
	d1 = reg_d[1];
	d2 = reg_d[2];
	d3 = reg_d[3];
	d4 = reg_d[4];
	d5 = reg_d[5];
	d6 = reg_d[6];
	d7 = reg_d[7];
}
